#include "CharCreator.h"

//constants
const int BASEAC = 10; // D&D 3.5 base armor class is 10

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//****************************************************** CharCreator class*******************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CharCreator::CharCreator() // default constructor initializes all values to defaults
{
        curStr = curDex = curCon = curInt = curWis = curCha = 8;
        abilityPoints = 25;
        curRace = NULL;
        curClass = NULL;
        name = "";
}

char* CharCreator::setRace(char* inputRace)
{
        if (curRace) delete curRace;
        curRace = new RaceTemplate();
        return "";
}
char* CharCreator::setClass(char* inputClass)
{
        if (curClass) delete curClass;
        curClass = new ClassTemplate();
        if(0)// this will never happen. should be if(!curClass) or if(curClass == 0)
        {
                //this is where I would handle not having found the specified race
                return "Error, class not found!";
        }
        return "";
}
// initializes a character, and returns it.
// Race, Class, and name must be set first with the setRace, setClass and setName functions.
// Also, all ability points must be used.
Character* CharCreator::instantiate()
{
        Character* charInstance = new Character();
        charInstance->state = "ERROR:\n";       //this is just for error string formatting. state will be set to "" if valid at end of checks.
        if (!curRace)
        {
                charInstance->valid = false;
                charInstance->state += "No race was specified.\n";
        }
        if (!curClass)
        {
                charInstance->valid = false;
                charInstance->state += "No class was specified.\n";
        }
        if (abilityPoints)
        {
                charInstance->valid = false;
                charInstance->state += "There were unused ability points!";
        }
        if (name == "")
        {
                charInstance->valid = false;
                charInstance->state += "Character had no name!";
        }
        if (charInstance->valid)
        {
                charInstance->state = "";       //only used if character instance is invalid
                charInstance->baseClass = curClass;
                charInstance->baseRace = curRace;
                charInstance->name = name;
                charInstance->curHP = charInstance->maxHP = curClass->hitDice;
                charInstance->AC = BASEAC;
                charInstance->speed = curRace->speed;
				charInstance->baseStr = curStr + curRace->strBonus;
				charInstance->baseDex = curDex + curRace->dexBonus;
				charInstance->baseCon = curCon + curRace->conBonus;
				charInstance->baseInt = curInt + curRace->intBonus;
				charInstance->baseWis = curWis + curRace->wisBonus;
				charInstance->baseCha = curCha + curRace->chaBonus;
                charInstance->initiative = charInstance->getDexMod();
                charInstance->level = 1;
        }
        return charInstance;
}

char* CharCreator::changeAttribute(int& attribute, bool add1)
{
                        /*      How The Attributes work: (as per page 169 of the dungeon master's guide)
                        Each stat begins at 8.
                        A stat of 9 costs 1 point.
                        A stat of 10 costs 2 points.
                        A stat of 11 costs 3 points.
                        A stat of 12 costs 4 points.
                        A stat of 13 costs 5 points.
                        A stat of 14 costs 6 points.
                        A stat of 15 costs 8 points.
                        A stat of 16 costs 10 points.
                        A stat of 17 costs 13 points.
                        A stat of 18 costs 16 points.*/
        if (attribute < 8) return "Error, base ability score below 9, Please contact software support!"; // base should always be >7
        if (attribute > 18) return "Error, base ability score above 18, please contact software support!"; // base should always be <19

        if (add1)
        {
                if ((attribute <14)&&(abilityPoints > 0))
                        return statMod(attribute, 1, -1);
                else if ((attribute <16)&&(abilityPoints > 1))
                        return statMod(attribute, 1, -2);
                else if ((attribute <18)&&(abilityPoints > 2))
                        return statMod(attribute, 1, -3);
                else if (attribute == 18) 
                        return "You cannot increase base stats over 18";
                else return "You do not have enough ability points to make this increase";
        }else
        {
                if (attribute > 16) 
                        return statMod(attribute, -1, 3);
                else if (attribute > 14)
                        return statMod(attribute, -1, 2);
                else  if (attribute > 8) return statMod(attribute, -1, 1);
                else return "You cannot decrease a base stat below 8";
                
        }
}
char* CharCreator::statMod(int& attribute,int amount, int cost)
{
        abilityPoints += cost;
        attribute += amount;
        return "";
}
void CharCreator::autoAssignPoints()
{
	this->setClass("Fight");
	this->setRace("Human");
	this->setName("NewChar");
	while(abilityPoints > 0)
	{
		changeStr(true);
		changeDex(true);
		changeCon(true);
		changeInt(true);
		changeWis(true);
		changeCha(true);
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************************************************Character Class*******************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Character::Character()
{
        valid = true;
        state = "Uninitialized";
        baseClass = NULL;
        baseRace = NULL;
        name ="";
        XP = curHP = maxHP = AC = speed = initiative = baseStr = baseDex = baseCon = baseInt = baseWis = baseCha = strBonus = dexBonus = 0;
        conBonus = intBonus = wisBonus = chaBonus = 0;
}
void Character::adjustHP(int HPToAdd)
{
        curHP += HPToAdd;
        if (curHP > maxHP)
                curHP = maxHP;
}
void Character::adjustXP(int XPToAdd)
{
        XP += XPToAdd;
        if (XP < 0) XP = 0;
        updateLevel();
}
void Character::updateLevel()
{
        const int LEVEL2 = 1000;
        const int LEVEL3 = 3000;
        const int LEVEL4 = 6000;
        const int LEVEL5 = 10000;
        const int LEVEL6 = 15000;
        const int LEVEL7 = 21000;
        const int LEVEL8 = 28000;
        const int LEVEL9 = 36000;
        const int LEVEL10 = 45000;
        const int LEVEL11 = 55000;
        const int LEVEL12 = 66000;
        const int LEVEL13 = 78000;
        const int LEVEL14 = 91000;
        const int LEVEL15 = 105000;
        const int LEVEL16 = 120000;
        const int LEVEL17 = 136000;
        const int LEVEL18 = 153000;
        const int LEVEL19 = 171000;
        const int LEVEL20 = 190000;
        if (XP < LEVEL2)
                Leveler(1);
        else if (XP < LEVEL3)
                Leveler(2);
        else if (XP < LEVEL4)
                Leveler(3);
        else if (XP < LEVEL5)
                Leveler(4);
        else if (XP < LEVEL6)
                Leveler(5);
        else if (XP < LEVEL7)
                Leveler(6);
        else if (XP < LEVEL8)
                Leveler(7);
        else if (XP < LEVEL9)
                Leveler(8);
        else if (XP < LEVEL10)
                Leveler(9);
        else if (XP < LEVEL11)
                Leveler(10);
        else if (XP < LEVEL12)
                Leveler(11);
        else if (XP < LEVEL13)
                Leveler(12);
        else if (XP < LEVEL14)
                Leveler(13);
        else if (XP < LEVEL15)
                Leveler(14);
        else if (XP < LEVEL16)
                Leveler(15);
        else if (XP < LEVEL17)
                Leveler(16);
        else if (XP < LEVEL18)
                Leveler(17);
        else if (XP < LEVEL19)
                Leveler(18);
        else if (XP < LEVEL20)
                Leveler(19);
        else Leveler(20);
}
void Character::Leveler(int inputLevel)
{
        if (level != inputLevel)
        {
                level = inputLevel;
                maxHP = baseClass->hitDice*inputLevel;
                if (curHP > maxHP)
                        curHP = maxHP;
        }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************************************************----------------*******************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******************************************************----------------*******************************************************************
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*#include <iostream>

using namespace std;
//test code goes here
int main()
{
        CharCreator* exampleCC = new CharCreator();
        cout << "Strength is currently: " << exampleCC->getStr() << endl << "Ability points are currently: " << exampleCC->getAbilityPoints() 
                << endl << endl << "Adding 5 to strength..." << endl;
        for (int i = 0; i < 5; ++i)
                exampleCC->changeStr(true);
        cout << "Strength is now: " << exampleCC->getStr() << endl << "Ability points are now: " << exampleCC->getAbilityPoints() << endl 
                << endl << "adding 5 to strength..." << endl;
        for (int i = 0; i < 5; ++i)
                exampleCC->changeStr(true);
        cout << "Strength is now: " << exampleCC->getStr() << endl << "Ability points are now: " << exampleCC->getAbilityPoints() << endl 
                << endl << "adding one more to strength..." << endl;
        cout << exampleCC->changeStr(true) << endl << endl;
                
        cout << "adding seven to dexterity and one to constitution" << endl << endl;
        for (int i = 0; i < 7; ++i)
                exampleCC->changeDex(true);
        exampleCC->changeCon(true);
        cout << "dex is: " << exampleCC->getDex() << endl << "con is: " << exampleCC->getCon() << endl << "ability points are: " 
                        << exampleCC->getAbilityPoints() << endl << endl;

        cout << "adding one more to con..." << endl << endl;
        cout << exampleCC->changeCon(true) << endl << endl;

        cout << "Subtracting one from Charisma" << endl << exampleCC->changeCha(false) << endl << endl;
        cout << "Charisma is: " << exampleCC->getCha() << endl << endl;


        cout << "setting character's race, class, and name (to Milford), and instantiating!" << endl;

        exampleCC->setClass("foo");
        exampleCC->setRace("bar");
        exampleCC->setName("Milford");
        Character* exampleChar = exampleCC->instantiate();

        cout << "Character's name is now: " << exampleChar->getName() << endl;
        cout << "Character's race is now: " << exampleChar->getRace() << endl;
        cout << "Character's class is now: " << exampleChar->getClass() << endl;
        cout << "Character's speed is now: " << exampleChar->getSpeed() << endl;
        cout << "Character's stats are:\t\tmodifier:" << endl 
                        << "Strength: " << exampleChar->getStr() << "\t\t\t" << exampleChar->getStrMod() << endl
                        << "Dexterity: " << exampleChar->getDex() << "\t\t\t" << exampleChar->getDexMod() << endl
                        << "Constitution: " << exampleChar->getCon() << "\t\t\t" << exampleChar->getConMod() << endl
                        << "Intelligence: " << exampleChar->getInt() << "\t\t\t" << exampleChar->getIntMod() << endl
                        << "Wisdom: " << exampleChar->getWis() << "\t\t\t" << exampleChar->getWisMod() << endl
                        << "Charisma: " << exampleChar->getCha() << "\t\t\t" << exampleChar->getChaMod() << endl;
        cout << "Character's AC is: " << exampleChar->getAC() << endl;
        cout << "Character's initiative is: " << exampleChar->getInit() << endl;

        cout << "Character's XP is now: " << exampleChar->getXP() << endl;
        cout << "Character's level is now: " << exampleChar->getLevel() << endl;
        cout << "Character's hps are: " << exampleChar->getCurHP() << '/' << exampleChar->getMaxHP() << endl << endl;
        cout << "Character's Fortitude save is: " << exampleChar->getFortSave() << endl;
        cout << "Character's Will save is: " << exampleChar->getWillSave() << endl;
        cout << "Character's Reflex save is: " << exampleChar->getReflexSave() << endl;

        cout << "giving character 10,000 xp!" << endl << endl; 
        exampleChar->adjustXP(10000);

        cout << "Characer's XP is now: " << exampleChar->getXP() << endl;
        cout << "Character's level is now: " << exampleChar->getLevel() << endl;
        cout << "Character's hps are: " << exampleChar->getCurHP() << '/' << exampleChar->getMaxHP() << endl;
        cout << "Character's Fortitude save is: " << exampleChar->getFortSave() << endl;
        cout << "Character's Will save is: " << exampleChar->getWillSave() << endl;
        cout << "Character's Reflex save is: " << exampleChar->getReflexSave() << endl;
        cout << "Healing character by 30 points!" << endl;
        exampleChar->adjustHP(30);
        cout << "Character's hps are: " << exampleChar->getCurHP() << '/' << exampleChar->getMaxHP() << endl;
                
        cout << "Taking 5,000 xp from player!" << endl << endl; 
        exampleChar->adjustXP(-5000);
                
        cout << "Character's XP is now: " << exampleChar->getXP() << endl;
        cout << "Character's level is now: " << exampleChar->getLevel() << endl;
        cout << "Character's hps are: " << exampleChar->getCurHP() << '/' << exampleChar->getMaxHP() << endl;
        cout << "Character's Fortitude save is: " << exampleChar->getFortSave() << endl;
        cout << "Character's Will save is: " << exampleChar->getWillSave() << endl;
        cout << "Character's Reflex save is: " << exampleChar->getReflexSave() << endl;
        cout << "Damaging Character by 10 points!" << endl;
        exampleChar->adjustHP(-10);
        cout << "Character's hps are: " << exampleChar->getCurHP() << '/' << exampleChar->getMaxHP() << endl;

        cout << endl;
        system("PAUSE");
        return 0;
}

*/